package com.aiyige.page.player.widget;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;

import com.aiyige.R;

/**
 * Created by zhuyakun on 2017/9/30.
 */

public class PlayerSeekBar extends ConstraintLayout {
    public static final String TAG = PlayerSeekBar.class.getSimpleName();
    public static final long DEFAULT_RANGE_GAP_MS = 1000;
    SeekBar pcSeekBar;
    View pcRangeStartLayout;
    View pcRangeEndLayout;
    View pcRangeBgView;
    ImageView pcRangeStartIv;
    ImageView pcRangeEndIv;
    ViewDragHelper viewDragHelper;
    Drawable invisiableSeekBarProgress;
    Drawable visiableSeekBarProgress;
    boolean showRangeView;
    int progressRangeStart = 0;
    int progressRangeEnd = Integer.MAX_VALUE;
    long mediaDurationMs;
    int pcRangeGapPixel;
    long pcRangeGapMs;
    int pcRangeStartLayoutLeft = -1;
    int pcRangeEndLayoutLeft = -1;
    PlayerSeekBarListener listener;

    public PlayerSeekBar(@NonNull Context context) {
        super(context);
        init();
    }

    public PlayerSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PlayerSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public long getMediaDurationMs() {
        return mediaDurationMs;
    }

    public void setMediaDurationMs(long mediaDurationMs) {
        this.mediaDurationMs = mediaDurationMs;
        calculateRangeGapPixel();
    }


    public void setRangeGapMs(long gapMs) {
        pcRangeGapMs = gapMs;
        calculateRangeGapPixel();
    }

    public long getRangeGapMs() {
        return pcRangeGapMs;
    }

    public void calculateRangeGapPixel() {
        if (mediaDurationMs == 0) return;
        pcRangeGapPixel = (int) ((float) pcRangeBgView.getMeasuredWidth() * pcRangeGapMs / mediaDurationMs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        calculateRangeGapPixel();
        if (pcRangeStartLayoutLeft >= 0) {
            int width = pcRangeStartLayout.getWidth();
            pcRangeStartLayout.setLeft(pcRangeStartLayoutLeft);
            pcRangeStartLayout.setRight(pcRangeStartLayoutLeft + width);
        }
        if (pcRangeEndLayoutLeft >= 0) {
            int width = pcRangeEndLayout.getWidth();
            pcRangeEndLayout.setLeft(pcRangeEndLayoutLeft);
            pcRangeEndLayout.setRight(pcRangeEndLayoutLeft + width);
        }
        if (pcRangeStartLayoutLeft >= 0 || pcRangeEndLayoutLeft >= 0) {
            updateRange();
        }

    }

    public void setListener(PlayerSeekBarListener listener) {
        this.listener = listener;
    }

    public void init() {
        LayoutInflater.from(getContext()).inflate(R.layout.player_seek_bar, this, true);
        showRangeView = false;
        listener = null;
        pcRangeGapMs = DEFAULT_RANGE_GAP_MS;
        pcRangeGapPixel = 0;
        pcSeekBar = (SeekBar) findViewById(R.id.pc_seekBar);
        pcRangeStartLayout = findViewById(R.id.pc_rangeStartLayout);
        pcRangeEndLayout = findViewById(R.id.pc_rangeEndLayout);
        pcRangeStartIv = (ImageView) findViewById(R.id.pc_rangeStartIv);
        pcRangeEndIv = (ImageView) findViewById(R.id.pc_rangeEndIv);
        pcRangeBgView = findViewById(R.id.pc_rangeBgView);
        invisiableSeekBarProgress = getContext().getResources().getDrawable(R.drawable.invisiable_seek_bar_progress);
        visiableSeekBarProgress = getContext().getResources().getDrawable(R.drawable.visiable_seekbar_progress);
        viewDragHelper = ViewDragHelper.create(this, 10.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return child.getId() == R.id.pc_rangeStartIv ||
                        child.getId() == R.id.pc_rangeStartLayout ||
                        child.getId() == R.id.pc_rangeEndIv ||
                        child.getId() == R.id.pc_rangeEndLayout;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                int realLeft;
                if (child.getId() == R.id.pc_rangeStartIv || child.getId() == R.id.pc_rangeStartLayout) {
                    realLeft = Math.max(0, Math.min(left, pcRangeEndLayout.getLeft() - pcRangeStartLayout.getMeasuredWidth() - pcRangeGapPixel));
                } else {
                    realLeft = Math.max(pcRangeStartLayout.getRight() + pcRangeGapPixel, Math.min(left, getMeasuredWidth() - pcRangeEndLayout.getMeasuredWidth()));
                }
                updateRange();
                return realLeft;
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                updateRange();
                return child.getTop();
            }

            @Override
            public int getViewHorizontalDragRange(View child) {
                return 1;
            }

            @Override
            public int getViewVerticalDragRange(View child) {
                return 1;
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);
                updateRange();
            }
        });
        pcSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    System.out.println("xcxc11 来自用户的" + progress);
                }
                listener.onProgressChanged(seekBar, progress, fromUser);
                if (showRangeView) {
                    if (progress < progressRangeStart || progress > progressRangeEnd) {
                        seekBar.setProgress(Math.max(progressRangeStart, Math.min(seekBar.getProgress(), progressRangeEnd)));
                    } else {
                        if (fromUser) {
                            listener.onSeek((long) ((float) progress / seekBar.getMax() * mediaDurationMs));
                        } else if (progress >= progressRangeEnd) {
                            listener.onSeek((long) ((float) progressRangeStart / seekBar.getMax() * mediaDurationMs));
                        }
                    }
                } else if (fromUser) {
                    listener.onSeek((long) ((float) progress / seekBar.getMax() * mediaDurationMs));
                }

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                listener.onStartTrackingTouch(seekBar);
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                listener.onStopTrackingTouch(seekBar);
            }
        });
        updateRangeViewVisibility();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return viewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    public boolean isShowRangeView() {
        return showRangeView;
    }

    public void setShowRangeView(boolean showRangeView) {
        this.showRangeView = showRangeView;
        updateRangeViewVisibility();
    }

    public void updateRange() {
        pcRangeStartLayoutLeft = pcRangeStartLayout.getLeft();
        pcRangeEndLayoutLeft = pcRangeEndLayout.getLeft();
        pcRangeBgView.setLeft(pcRangeStartLayout.getRight());
        pcRangeBgView.setRight(pcRangeEndLayout.getLeft());
        progressRangeStart = (int) ((float) (pcRangeBgView.getLeft() - ((ConstraintLayout.LayoutParams) pcRangeBgView.getLayoutParams()).leftMargin) / pcRangeBgView.getMeasuredWidth() * pcSeekBar.getMax());
        progressRangeEnd = progressRangeStart + (int) ((float) pcRangeBgView.getWidth() / pcRangeBgView.getMeasuredWidth() * pcSeekBar.getMax());
        pcSeekBar.setProgress(Math.max(progressRangeStart, Math.min(pcSeekBar.getProgress(), progressRangeEnd)));
        if (pcSeekBar.getProgress() == progressRangeStart) {
            listener.onSeek((long) ((float) progressRangeStart / pcSeekBar.getMax() * mediaDurationMs));
        }
    }

    public void clearABPosition() {
        pcRangeStartLayoutLeft = -1;
        pcRangeEndLayoutLeft = -1;
        requestLayout();
    }

    public int getProgressRangeStart() {
        return progressRangeStart;
    }

    public void setProgressRangeStart(int progressRangeStart) {
        this.progressRangeStart = progressRangeStart;
    }

    public int getProgressRangeEnd() {
        return progressRangeEnd;
    }

    public void setProgressRangeEnd(int progressRangeEnd) {
        this.progressRangeEnd = progressRangeEnd;
    }

    public void setSecondaryProgress(int secondaryProgress) {
        pcSeekBar.setSecondaryProgress(secondaryProgress);
    }

    public void updateRangeViewVisibility() {
        pcRangeStartLayout.setVisibility(showRangeView ? VISIBLE : INVISIBLE);
        pcRangeEndLayout.setVisibility(showRangeView ? VISIBLE : INVISIBLE);
        pcRangeBgView.setVisibility(showRangeView ? VISIBLE : INVISIBLE);
        pcSeekBar.setProgressDrawable(showRangeView ? invisiableSeekBarProgress : visiableSeekBarProgress);
    }

    public void updateProgressMs(long positionMs) {
//        pcSeekBar.setProgress((int) ((float) positionMs / mediaDurationMs * pcSeekBar.getMax()));
        pcSeekBar.setProgress((int) positionMs);
    }

    public void updateSecondardProgress(float percentage) {
        pcSeekBar.setSecondaryProgress((int) (percentage * pcSeekBar.getMax()));
    }

    public SeekBar getSeekBar() {
        return pcSeekBar;
    }


    public interface PlayerSeekBarListener {
        void onStartTrackingTouch(SeekBar bar);

        void onProgressChanged(SeekBar bar, int progress, boolean fromuser);

        void onStopTrackingTouch(SeekBar bar);

        void onSeek(long position);
    }

}
